﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Facebook;
using System.ComponentModel;
using LinqExpression = System.Linq.Expressions;
using SoGame.ViewModels;
using System.Configuration;
using SoGame.Facebook.Winforms;
using System.IO;
using System.Drawing;

namespace SoGame.Helper
{
    public class FacebookHelper : INotifyPropertyChanged
    {
        private FacebookStatus status = FacebookStatus.Disconnected;
        private FacebookClient client;
        private static FacebookHelper instance = new FacebookHelper();

        /// <summary>
        /// Gets the instance.
        /// </summary>
        public static FacebookHelper Instance {
            get { return instance; }
        }

        /// <summary>
        /// Prevents a default instance of the <see cref="FacebookHelper"/> class from being created.
        /// </summary>
        private FacebookHelper() {
            //client = new FacebookClient(ConfigurationManager.AppSettings["FacebookAppId"]);
        }

        /// <summary>
        /// Gets the app id.
        /// </summary>
        public string AppId {
            get { return ConfigurationManager.AppSettings["FacebookAppId"]; }
            private set { ConfigurationManager.AppSettings["FacebookAppId"] = value; }
        }

        /// <summary>
        /// Gets the access token.
        /// </summary>
        public string AccessToken {
            get { return SoGame.Properties.Settings.Default.FacebookAccessToken; }
            private set { SoGame.Properties.Settings.Default.FacebookAccessToken = value; }
        }

        /// <summary>
        /// Gets or sets the experts token.
        /// </summary>
        /// <value>
        /// The experts token.
        /// </value>
        public string ExpertsToken {
            get { return SoGame.Properties.Settings.Default.FacebookExpertsToken; }
            private set { SoGame.Properties.Settings.Default.FacebookExpertsToken = value; }
        }

        /// <summary>
        /// Gets or sets the status.
        /// </summary>
        /// <value>
        /// The status.
        /// </value>
        public FacebookStatus Status {
            get { return this.status; }
            set {
                if (this.status != value) {
                    this.status = value;
                    this.OnPropertyChanged(() => this.Status);
                }
            }
        }

        /// <summary>
        /// Connects this instance.
        /// </summary>
        /// <returns></returns>
        public bool Connect() {
            if (this.status == FacebookStatus.Connected) {
                return true;
            }

            if (!string.IsNullOrEmpty(this.ExpertsToken)) {
                client = new FacebookClient(this.ExpertsToken);
                this.Status = FacebookStatus.Connected;
                return true;
            }

            // ouverture d'un dialogue et requête facebook avec la demande de droits nécessaires
            using (var loginDialog = new FacebookLoginDialog(
                        this.AppId, 
                        new string[] { "manage_pages", "publish_actions", "publish_stream", 
                            "offline_access", "photo_upload", "read_stream" })) {
                if (loginDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) {
                    // récupération du token de l'utilisateur
                    this.AccessToken = loginDialog.FacebookOAuthResult.AccessToken;

                    if (string.IsNullOrEmpty(this.AccessToken)) {
                        return false;
                    }

                    // récupération du token "So@t Experts .NET" pour écrire sur le mur
                    // avec ce nom... sinon, on va écrire avec le nom de la personne qui
                    // ce sera connecté !
                    client = new FacebookClient(this.AccessToken);
                    dynamic accounts = client.Get("/me/accounts");
                    int i = -1;
                    // on recherche l'account 
                    while (++i < accounts.data.Count && accounts.data[i].name != ConfigurationManager.AppSettings["FacebookAccountName"]) ;

                    if (accounts.data[i].name != ConfigurationManager.AppSettings["FacebookAccountName"]) {
                        return false;
                    }

                    // on récupère le token
                    this.ExpertsToken = accounts.data[i].access_token;
                    // on instancie un client
                    this.client = new FacebookClient(this.ExpertsToken);
                    // on informe que l'on est connecté !
                    this.Status = FacebookStatus.Connected;

                    // on enregistre les paramètres de configuration
                    SoGame.Properties.Settings.Default.Save();

                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// Posts the message.
        /// </summary>
        /// <param name="message">The message.</param>
        /// <returns></returns>
        public string PostMessage(string message) {
            if (this.Status == FacebookStatus.Disconnected) {
                return string.Empty;
            }

            dynamic ret = this.client.Post("/me/feed", new Dictionary<string, object> { { "message", message } });

            return ret.id;
        }

        /// <summary>
        /// Posts the image.
        /// </summary>
        /// <param name="imagePath">The image path.</param>
        /// <returns></returns>
        public void PostImage(string imagePath, string message) {
            PostImage(File.ReadAllBytes(imagePath), Path.GetFileName(imagePath), message);
        }

        public void PostImage(byte[] imageBuffer, string fileName, string message)
        {
            if (this.Status == FacebookStatus.Disconnected)
            {
                return; // string.Empty;
            }

            var mediaObject = new FacebookMediaObject
            {
                ContentType = "image/jpeg",
                FileName = fileName
            }.SetValue(imageBuffer);

            client.PostAsync("/me/photos", new Dictionary<string, object> { { "source", mediaObject }, { "message", message } });

            //return ret.id;
        }

        #region Propertychanged
        protected void OnPropertyChanged<T>(LinqExpression.Expression<Func<T>> action)
        {
            var propertyName = GetPropertyName(action);
            OnPropertyChanged(propertyName);
        }

        private static string GetPropertyName<T>(LinqExpression.Expression<Func<T>> action)
        {
            var expression = (LinqExpression.MemberExpression)action.Body;
            var propertyName = expression.Member.Name;
            return propertyName;
        }

        private void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                var e = new PropertyChangedEventArgs(propertyName);
                handler(this, e);
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        #endregion

    }
}
